package com.fingard.dsp.bank.directbank.hrbb01.util;

import java.io.ByteArrayOutputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterOutputStream;

import org.apache.commons.codec.binary.Base64;

public class Base64Util {

	static private char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
	static private byte[] codes = new byte[256];
	static {
		for (int i = 0; i < 256; i++)
			codes[i] = -1;
		for (int i = 'A'; i <= 'Z'; i++)
			codes[i] = (byte) (i - 'A');
		for (int i = 'a'; i <= 'z'; i++)
			codes[i] = (byte) (26 + i - 'a');
		for (int i = '0'; i <= '9'; i++)
			codes[i] = (byte) (52 + i - '0');
		codes['+'] = 62;
		codes['/'] = 63;
	}  
	           
    /** 
     * 将原始数据编码为base64编码 
     */  
	public static String encode(byte[] data) {
		char[] out = new char[((data.length + 2) / 3) * 4];
		for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
			boolean quad = false;
			boolean trip = false;
			int val = (0xFF & (int) data[i]);
			val <<= 8;
			if ((i + 1) < data.length) {
				val |= (0xFF & (int) data[i + 1]);
				trip = true;
			}
			val <<= 8;
			if ((i + 2) < data.length) {
				val |= (0xFF & (int) data[i + 2]);
				quad = true;
			}
			out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
			val >>= 6;
			out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
			val >>= 6;
			out[index + 1] = alphabet[val & 0x3F];
			val >>= 6;
			out[index + 0] = alphabet[val & 0x3F];
		}

		return new String(out);
	}  
	  
	/** 
	 * 将base64编码的数据解码成原始数据 
	 */  
	public static  byte[] decode(String encode) throws Exception { 
		char[] data = new char[encode.length()];
		for(int i=0;i<encode.length();i++){
			 data[i] = encode.charAt(i);
		}
		
		int len = ((data.length + 3) / 4) * 3;  
	    if (data.length > 0 && data[data.length - 1] == '=')  
	         --len;  
		if (data.length > 1 && data[data.length - 2] == '=')  
	         --len;  
		byte[] out = new byte[len];  
		int shift = 0;  
		int accum = 0;  
	    int index = 0;  
		for (int ix = 0; ix < data.length; ix++) {  
			int value = codes[data[ix] & 0xFF];  
			if (value >= 0) {  
				accum <<= 6;  
				shift += 6;  
				accum |= value;  
		        if (shift >= 8) {  
		        	shift -= 8;  
		            out[index++] = (byte) ((accum >> shift) & 0xff);  
		        }  
			}  
		}  
		if (index != out.length)  
			throw new Exception("base64 decode:miscalculated data length!");  
		return out;  
	}  
	        
    //压缩字符串
	public static String compressData(String data) {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			DeflaterOutputStream zos = new DeflaterOutputStream(bos);
			zos.write(data.getBytes());
			zos.close();
			return new String(getenBASE64inCodec(bos.toByteArray()));
		} catch (Exception ex) {
			ex.printStackTrace();
			return "ZIP_ERR";
		}
	}
	
	//解码字符串
	public static String decompressData(String encdata) {
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			InflaterOutputStream zos = new InflaterOutputStream(bos);
			zos.write(getdeBASE64inCodec(encdata)); 
			zos.close();
			return new String(bos.toByteArray());
		} catch (Exception ex) {
			ex.printStackTrace();
			return "UNZIP_ERR";
		}
	}
	    	
	//使用apche codec对数组进行encode
	public static String getenBASE64inCodec(byte [] b) {
		if (b == null)
			return null;
		return new String((new Base64()).encode(b));
	}
	    	
	//base64转码为string
	public static byte[] getdeBASE64inCodec(String s) {
		if (s == null)
			return null;
		return new Base64().decode(s.getBytes());
	}
	    	
	public static void main(String[] args) throws Exception {
        String encode = Base64Util.encode("a2bc1dko4".getBytes());
        System.out.println("encode:"+encode);
        String decode = new String(Base64Util.decode(encode));
        System.out.println("decode:"+decode);
        String data = "CBE001|CB10000068|1106|#<?xmlversion=\"1.0\"encoding=\"GBK\"?><BankData><opReq><bsnCode>CBE001</bsnCode><serialNo>1548899526199</serialNo><reqTime>20190131135429</reqTime><ReqParam><accountNo>18010000001244562</accountNo></ReqParam></opReq></BankData>";
        System.out.println(Base64Util.compressData(data));
	}
}
